package pr3.seleccion;

import java.util.List;

import pr3.AlgoritmoGenetico;
import pr3.cromosoma.Cromosoma;

public class Ranking<E extends Cromosoma<E>> implements EstrategiaSeleccion<E> {

	private double presionSelectiva;

	public Ranking(double ps) {
		this.presionSelectiva = ps;
	}

	@Override
	public String getNombre() {
		return "Ranking";
	}

	@Override
	public void seleccion(List<E> poblacion, List<E> seleccionados,
			AlgoritmoGenetico<E> algoritmoGenetico) {

		seleccionados.set(0, poblacion.get(0).clone());
		seleccionados.set(1, poblacion.get(1).clone());

		int numOfParents = 2;

		double[] fitnessSegments = rankPopulation(poblacion.size());
		double entireSegment = fitnessSegments[fitnessSegments.length - 1];

		while (numOfParents < seleccionados.size()) {

			double x = (double) (Math.random() * entireSegment);

			if (x <= fitnessSegments[0]) {
				/*** First Idividual was Selected **/
				seleccionados.set(numOfParents, poblacion.get(0).clone());
				numOfParents++;
			} else {
				for (int i = 1; i < seleccionados.size(); i++)
					if (x > fitnessSegments[i - 1] && x <= fitnessSegments[i]) {
						/*** i'th Idividual was Selected **/
						seleccionados.set(numOfParents, poblacion.get(i).clone());
						numOfParents++;
					}
			}
		}
	}

	private double[] rankPopulation(int populationSize) {
		
		double[] fitnessSegments = new double[populationSize];
		
		for (int i = 0; i < fitnessSegments.length; i++) {
			
			double probOfIth = (double) i / populationSize;
			probOfIth = probOfIth * 2 * (this.presionSelectiva - 1);
			probOfIth = this.presionSelectiva - probOfIth;
			probOfIth = (double) probOfIth
					* ((double) 1 / this.presionSelectiva);
			
			if (i != 0)
				fitnessSegments[i] = fitnessSegments[i - 1] + probOfIth;
			else
				fitnessSegments[i] = probOfIth;
		}
		
		return fitnessSegments;
	}
}
